package Main;


import javax.microedition.lcdui.*;
import javax.microedition.location.Criteria;

import Common.CRes;
import Common.MyVT;
import Entity.Line;
import Entity.Point;
import Entity.Rec;

public abstract class CObject
{
	public static final byte FRIENDLY=1;
	public static final byte UNFRIENDLY=-1;
	public static final byte NEUTRAL=0;
	
	public  int bx, by, p1, p2, p3;
	public static int z0=100;
	public static int xView,yView;
	
	public int x,y,z; 					// object position
	public int w,h; 					// object size
	public int vx,vy;					// van toc theo phuong x, phuong y
	public  static int vmax=196;		// van toc lon nhat
	public boolean sleep;				// bao object dang cho
	public boolean deleted;				// bao object da bi xoa
	
	private int dx,dy;					// khoang dich chuyen theo phuong x,y
	
	public CObject()
	{
	}
	
	public CObject(int x,int y,int w,int h)
	{
		set(x,y,w,h);
	}
	
	public void set(int x,int y,int w,int h)
	{
		this.x=x;
		this.y=y;
		this.w=w;
		//hw=w>>1;
		this.h=h;
	}
	
	public void setPos(int x,int y)
	{
		this.x=x;
		this.y=y;
	}
	
	public void setSize(int w,int h)
	{
		this.w=w;
		this.h=h;
	}
	
	/*public void move()
	{
		dx+=vx;
		x+=dx>>10;
		dx=dx & 0x3ff;
		dy+=vy;
		y+=dy>>10;
		dy=dy & 0x3ff;
	}*/
	
	public void move(int dx, int dy){
		x+=dx;
		y+=dy;
	}
	
	public void move()
	{
		
	}
	//diem cat nhau giua hai duong thang
	public Point intersection(double x1, double y1, double x2, double y2,double x3, double y3, double x4, double y4)//I didn't write this. got it from http://www.ahristov.com/tutorial/geometry-games/intersection-lines.html (I altered it)
    {
         double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);

         double xi = ((x3 - x4) * (x1 * y2 - y1 * x2) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
         double yi = ((y3 - y4) * (x1 * y2 - y1 * x2) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;

         int x=(int)xi;
         int y=(int)yi;
         System.out.println(">>>  "+x+","+y);
         return new Point(x, y);
     }
	void rectangleLine(Line Temp)
    {
            Line Line=(Line)Temp;
//            if(new Line2D.Double(Line.x1,Line.y1,Line.x2,Line.y2).intersects(new Rec(this.x,this.y,this.w,this.h)))
//            {
                if (Line.x < (this.x + this.w) && (Line.x) > this.x && Line.y < (this.y + this.h) && Line.y > this.y)//circle may be hitting one of the end points
                {
                    Rec rec=new Rec(this.x, Line.y, 1, 1);
                    this.rectangleRectangle(rec);
                    //remove(rec);
                }

                if (Line.xEnd < (this.x + this.w) && (Line.xEnd) > this.x && Line.yEnd < (this.y + this.h) && Line.yEnd > this.y)//circle may be hitting one of the end points
                {
                    Rec rec=new Rec(Line.xEnd, Line.yEnd, 1, 1);
                    rectangleRectangle(rec);
                    //remove(rec);
                }

                //if(Line.posSlope)//positive sloped line
                if(true)
                {
                    //first we'll do the top left corner
                    int x1=this.x-Line.h;
                    int x2=this.x+Line.h;
                    int y1=this.y-Line.w;
                    int y2=this.y+Line.w;
                    Point topPoint=new Point(-99,-99), botPoint=new Point(-99,-99);
                    double topDistance=0, botDistance=0;

                    topPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x,(double)Line.y,(double)Line.xEnd,(double)Line.yEnd);//find intersection

                    topDistance = Math.sqrt(CRes.pow(this.x - topPoint.x,2) + CRes.pow(this.y - topPoint.y, 2));

                    //new let's do the bottom right corner
                    x1=this.x+this.w-Line.h;
                    x2=this.x+this.w+Line.h;
                    y1=this.y+this.h-Line.w;
                    y2=this.y+this.h+Line.w;

                    botPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x,(double)Line.y,(double)Line.xEnd,(double)Line.yEnd);//find intersection

                    botDistance = Math.sqrt(CRes.pow((this.x+this.w) - botPoint.x,2) + CRes.pow((this.y+this.h) - botPoint.y, 2));


                    if(topDistance<botDistance)
                    {
                        if(new Rec(this.x,this.y,this.w,this.h).Contains(topPoint) && new Rec(this.x,this.y,Line.w,Line.h).Contains(topPoint))
                        {
                            this.move(topPoint.x,topPoint.y);
                            System.out.println("collision detected!");
                        }
                    }
                    else
                    {
                        if(new Rec(this.x,this.y,this.w,this.h).Contains(botPoint) && new Rec(Line.x,Line.y,Line.w,Line.h).Contains(botPoint))
                        {
                        	this.move(botPoint.x-this.w,botPoint.y-this.h);
                        	System.out.println("collision detected!");
                        }
                    }
                }
                else//negative sloped line
                {
//                    //first we'll do the top right corner
//                    int x1=Tile.x+Tile.width-Line.height;
//                    int x2=Tile.x+Tile.width+Line.height;
//                    int y1=Tile.y+Line.width;
//                    int y2=Tile.y-Line.width;
//                    Point topPoint=new Point(-99,-99), botPoint=new Point(-99,-99);
//                    double topDistance=0, botDistance=0;
//
//                    topPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
//
//                    topDistance = Math.sqrt(Math.pow(Tile.x + Tile.width - topPoint.x,2) + Math.pow(Tile.y - topPoint.y, 2));
//
//                    //new let's do the bottom left corner
//                    x1=Tile.x-Line.height;
//                    x2=Tile.x+Line.height;
//                    y1=Tile.y+Tile.height+Line.width;
//                    y2=Tile.y+Tile.height-Line.width;
//
//                    botPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
//
//                    botDistance = Math.sqrt(Math.pow(Tile.x - botPoint.x,2) + Math.pow((Tile.y+Tile.height) - botPoint.y, 2));
//
//
//                    if(topDistance<botDistance)
//                    {
//                        if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(topPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(topPoint))
//                        {
//                            Tile.move(topPoint.x-Tile.width,topPoint.y);text.out="collision detected!";
//                        }
//                    }
//                    else
//                    {
//                        if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(botPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(botPoint))
//                        {
//                            Tile.move(botPoint.x,botPoint.y-Tile.height);text.out="collision detected!";
//                        }
//                    }
                }
//            }
    }
	public void rectangleRectangle(Rec Temp)
    {
        int lapTop, lapBot, lapLeft, lapRight, small, scootX=0, scootY=0;

        lapTop=(Temp.y+Temp.h)-this.y;//top doi tuong
        lapBot=(this.y+this.h)-Temp.y;//bot
        lapLeft=(Temp.x+Temp.w)-this.x;
        lapRight=(this.x+this.w)-Temp.x;

        small=999999999;

        if (lapTop<small)
        {
        	small=lapTop; scootX=0; scootY=lapTop;
        }
        if (lapBot<small)
        {
        	small=lapBot; scootX=0; scootY=lapBot*-1;
        }
        if (lapLeft<small)
        {
        	small=lapLeft; scootX=lapLeft; scootY=0;
        }
        if (lapRight<small)
        {
        	small=lapRight; scootX=lapRight*-1; scootY=0;
        }

        System.out.println("collision detected!"+(this.x+scootX)+","+(this.y+scootY));
        this.move(this.x+scootX, this.y+scootY);
        //System.out.println("collision detected!");
    }
//	Input
//	LineA1	Point	First point on line A
//	LineA2	Point	Second point on line A
//	LineB1	Point	First point on line B
//	LineB2	Point	Second point on line B
//Output
//	True if lines collide
//Method
//	denom = ((LineB2.Y – LineB1.Y) * (LineA2.X – LineA1.X)) –
//		((LineB2.X – lineB1.X) * (LineA2.Y - LineA1.Y))
//	return denom != 0
	
	public boolean CollisionLineLine(Line line1, Line line2)
	{
		//Point a= new Point (line1.x,line1.y);
		/*a.x=line1.x
		 * a.y=line1.y
		 * b.x=line1.xEnd
		 * b.y=line1.yEnd
		 * c.x=line2.x
		 * c.y=line2.y
		 * d.x=line2.xEnd
		 * d.y=line2.yEnd
		 * */
		 
	    float denominator = ((line1.xEnd - line1.x) * (line2.yEnd -line2.y)) - ((line1.yEnd- line1.y) * (line2.xEnd - line2.x));
	    float numerator1 = ((line1.y-line2.y) * (line2.xEnd-line2.x)) - ((line1.x-line2.x) * (line2.yEnd-line2.y));
	    float numerator2 = ((line1.y-line2.y) * (line1.xEnd-line1.x)) - ((line1.x-line2.x) * (line1.yEnd-line1.y));

	    // Detect coincident lines (has a problem, read below)
	    if (denominator == 0) return numerator1 == 0 && numerator2 == 0;

	    float r = numerator1 / denominator;
	    float s = numerator2 / denominator;

	    return (r >= 0 && r <= 1) && (s >= 0 && s <= 1);
	}
	
	//execute rectangle collided line
	public boolean CollisionLineRectangle(Line line,Rec hitBox)
    {

        MyVT recVerts = new MyVT("Point");

        recVerts.addElement(new Point(hitBox.x, hitBox.y));
        recVerts.addElement(new Point(hitBox.x, hitBox.y + hitBox.h));
        recVerts.addElement(new Point(hitBox.x + hitBox.w, hitBox.y + hitBox.h));
        recVerts.addElement(new Point(hitBox.x + hitBox.w, hitBox.y));           

        if (
            //testing left side of rectangle
        	CollisionLineLine(line, new Line((Point)recVerts.elementAt(0),(Point)recVerts.elementAt(1)))
            ||
            //testing top side
            CollisionLineLine(line, new Line((Point)recVerts.elementAt(0),(Point)recVerts.elementAt(3)))
            ||
            //testing right side
            CollisionLineLine(line,new Line((Point)recVerts.elementAt(2),(Point)recVerts.elementAt(3)))
            ||
            //testing bottom
            CollisionLineLine(line,new Line((Point)recVerts.elementAt(1),(Point)recVerts.elementAt(2)))
            )
            {
                return true;
            }
        else
            return false;    
           
    }	
	
	// check colides with other game object
	public boolean collidesWith(CObject obj)
	{
		return (x+w>obj.x && x<obj.x+obj.w && 
			y+h>obj.y && y<obj.y+obj.h);
	}
	
	// check colides with rectange
	public boolean collidesWith(int x1,int y1,int w1,int h1)
	{
		return (x+w>x1 && x<x1+w1 && y+h>y1 && y<y1+h1);
	}
	
//	 check colides with point
	public boolean collidesWith(int x1,int y1)
	{
		return (x+w>x1 && x<x1 && y+h>y1 && y<y1);
	}
	public static boolean isPixelCollide(double x1, double y1, Image  image1,
            double x2, double y2, Image  image2) {
			// initialization
			double width1 = x1 + image1.getWidth() -1,
				height1 = y1 + image1.getHeight() -1,
				width2 = x2 + image2.getWidth() -1,
				height2 = y2 + image2.getHeight() -1;

			int xstart = (int) Math.max(x1, x2),
				ystart = (int) Math.max(y1, y2),
				xend   = (int) Math.min(width1, width2),
				yend   = (int) Math.min(height1, height2);

			// intersection rect
			int toty = Math.abs(yend - ystart);
			int totx = Math.abs(xend - xstart);

			for (int y=1;y < toty-1;y++){
				int ny = Math.abs(ystart - (int) y1) + y;
				int ny1 = Math.abs(ystart - (int) y2) + y;

				for (int x=1;x < totx-1;x++) {
					int nx = Math.abs(xstart - (int) x1) + x;
					int nx1 = Math.abs(xstart - (int) x2) + x;
					try {
//						if (((image1.getRGB(nx,ny) & 0xFF000000) != 0x00) &&
//								((image2.getRGB(nx1,ny1) & 0xFF000000) != 0x00))
//						if (((getPixel(image1,nx,ny)[0] & 0xFF000000) != 0x00) &&
//							((getPixel(image2,nx1,ny1)[0] & 0xFF000000) != 0x00))
//						{						
//							// collide!!
//							return true;
//						}
					} catch (Exception e) {
						//System.out.println("s1 = "+nx+","+ny+"  -  s2 = "+nx1+","+ny1);
					}
				}
			}

			return false;
}
	  public static  int[] getPixel(Image image, int x, int y) { 
		  int[] aux=new int[1];
		  image.getRGB(aux,0,image.getWidth(),x,y,1,1);
		  
		  int[] p=new int[3];
		  p[0]=(int)((aux[0]&0x00FF0000)>>>16); //Red level
		  p[1]=(int)((aux[0]&0x0000FF00)>>>8); //Green level
		  p[2]=(int)(aux[0]&0x000000FF); //Blue level
		  return p;
//	        int[] rgb = new int[image.getWidth() * image.getHeight()];  
//	        image.getRGB(rgb, 0, image.getWidth(), 0, 0, image.getWidth(), image.getHeight());  
//	  
//	        int pos = x + (y * image.getWidth());  
//	        return rgb[pos] << 16 | rgb[pos] << 8 | rgb[pos];  
	  
	    }
	//process method and must be override
	public void update()
	{
	}
	
	public void updateMove()
	{
	}
	
	//paint method and must be override
	public abstract void paint(Graphics g);
}